#include "ebm_env.h"
#include "ebm_msg.h"

#if 0
#define dbg(...)
#else
#define dbg printf
#endif

#if 0
#define msg_dbg(...)
#else
#define msg_dbg printf
#endif

const char* type_str[]={
"NULL",
"开始播发",
"停止播发",
"系统心跳",
"终端查询",
"终端参数设置",
};

static char* PARA_CMD_STR[]={
"无效",	
"音量",		
"本地IP地址信息",
"回传地址信息",
"地址信息",
"功放开关",
"校时",
"回传周期",
};

const char* pg_err_str[]={
"待机中",
"资源码不匹配",
"不支持的节目url",
"节目正常",
};


static struct pg_pri current_pg={0};
struct pg_pri *h_pg= &current_pg;
static char url_buf[PG_URL_LEN];


unsigned char is_current_pg_vaild(void)
{
	return h_pg->vaild;
}

void  current_pg_set(unsigned char radio_type, unsigned char rank, unsigned char *sid, unsigned char vol)
{
	
	if(radio_type > 5)
		radio_type=0;
	if(rank > 4)
		rank=0;
	h_pg->radio_type= radio_type;
	h_pg->rank= rank;
	h_pg->vol= vol;
	memcpy(h_pg->source_id, sid, PG_SOURCEID_LEN);
	h_pg->vaild= 1;
}

void  current_pg_clear(void)
{
	h_pg->vaild= 0;
}


static unsigned char parse_url(const char* url, unsigned int *ip, unsigned short *port)
{
	unsigned char ipstr_len;
	unsigned int tmp_ip; int tmp_port;
	char *p1,*p2;
	char ipbuf[20];
	memset(url_buf, 0, PG_URL_LEN);
	strncpy(url_buf, url, PG_URL_LEN);
	url_buf[PG_URL_LEN-1]=0;
	//dbg("url buf=%s\n", url_buf);
/*url类型1 udp://@24002*/
	p1= strstr(url_buf, "udp://@");
	if(p1 != NULL){
		*port= atoi(p1+ strlen("udp://@"));
		*ip= ebm_env_get_sip();
		return 1;
	}
	p1= strstr(url_buf, "rtp://");
	if(p1 == NULL){
		p1= strstr(url_buf, "udp://");
	}
	if(p1 == NULL){
		/*暂不支持rtsp*/
		return 0;
	}
	p1+= strlen("rtp://");
	//dbg("p1=%s\n", p1);
	p2= strstr(p1, ":");
	ipstr_len= p2-p1;
	if(p2 == NULL || ipstr_len > 15)
		return 0;
	
	strncpy(ipbuf, p1, ipstr_len);
	ipbuf[ipstr_len]=0;
	//dbg("ipbuf=%s\n", ipbuf);
	tmp_ip= inet_addr(ipbuf);
	tmp_ip= swap32(tmp_ip);
	//dbg("tmp_ip=%x\n", tmp_ip);
	tmp_port= atoi(p2+1);
	if(tmp_port <= 0 || tmp_port >= 0xffff)
		return 0;
	//dbg("tmp_port=%x\n", tmp_port);

	*ip= tmp_ip;
	*port= tmp_port;
	return 2;

}



static unsigned int _convet_priority(unsigned char radio_type, unsigned char rank)
{
	unsigned int pri=0x0;
	switch(radio_type){
		case 0x4:  //应急
			pri|= 0x30;
			break;
		case 0x5:  //日常
			pri|= 0x10;
			break;
		case 0x0:  //无效
			break;
		default:
			pri|= 0x20;
			break;
	}

	switch(rank){
		case 0x1:  //特别重大
			pri|= 0x4;
			break;
		case 0x2:  //重大
			pri|= 0x3;
			break;
		case 0x3:  //较大
			pri|= 0x2;
			break;
		default:
			break;
	}
	return pri;
}

#if 1
void _printf_sid(unsigned char *sid)
{
	unsigned char i;
	for(i =0; i<18; i++){
		dbg("%02x ", sid[i]);
	}
	dbg("\n");
}

#endif

static unsigned char _compare_pg_pri(CMD_PLAY_HEADER *new_pg)
{
	unsigned char ret=0;
	unsigned int new_pri, curent_pri;

	curent_pri= _convet_priority(h_pg->radio_type, h_pg->rank);
	new_pri= _convet_priority(new_pg->radio_type, new_pg->rank);
	if(new_pri <= curent_pri){
		dbg("not a pri pg embid= ");
		_printf_sid(new_pg->source_id);
		return 0;
	}
	return ret;
}

static unsigned char _compare_pg_sourceid(CMD_PLAY_HEADER *new_pg)
{
	unsigned char ret=0;
	if(0 == memcmp(h_pg->source_id, new_pg->source_id, PG_SOURCEID_LEN))
		ret=1;
	return ret;
}


static unsigned char _parse_pg_info(CMD_PLAY_HEADER *new_pg, unsigned int *ip, unsigned short *port)
{
	unsigned char ret=URL_UNVAILD;

	if(new_pg->assist_type != VAILD_ASSIST_TYPE)
		return URL_UNVAILD;
	
	if(0 == parse_url(&new_pg->assist_url, ip, port))
		return ret;
	
	//if(0 == ebm_rtp_visit_netsta(NULL, NULL) && 0 == is_current_pg_vaild()){
	if(0 == is_current_pg_vaild()){
		dbg("parse a new pg\n");
		current_pg_set(new_pg->radio_type, new_pg->rank, new_pg->source_id, new_pg->vol);
		ret=URL_VAILD_NEW;
	}
	else if(_compare_pg_sourceid(new_pg)){
		ret=URL_VAILD_LAST;
	}
	else if(_compare_pg_pri(new_pg)){
		dbg("parse a  higer pri pg\n");
		current_pg_set(new_pg->radio_type, new_pg->rank, new_pg->source_id, new_pg->vol);
		ret=URL_VAILD_HIGH_PRI;
	}
		
	return ret;
}


static void _log_pg_start(unsigned int ip, unsigned short port)
{
	char buf[40];
	unsigned char i;
	for(i=0;i<18;i++){
		sprintf(&buf[i*2], "%02X", h_pg->source_id[i]);
	}
	buf[39]=0;
	dbg("new pg %s url %d.%d.%d.%d:%d\n", buf,  ip >> 24, (ip>>16)&0xff, (ip>>8)&0xff, (ip)&0xff, port);
	if(h_pg->vol <= 100)
		sys_log("节目 %s url %d.%d.%d.%d:%d 音量:%d", buf,  ip >> 24, (ip>>16)&0xff, (ip>>8)&0xff, (ip)&0xff, port, h_pg->vol);
	else
		sys_log("节目 %s url %d.%d.%d.%d:%d", buf,  ip >> 24, (ip>>16)&0xff, (ip>>8)&0xff, (ip)&0xff, port);
}

void parse_cmd_play(unsigned char *data)
{
	unsigned char result=0;/*0.无效的url，1. url是原来的节目 ，2.url是新节目*/
	unsigned int ip=0;
	unsigned short port=0;
	CMD_PLAY_HEADER *pg= (CMD_PLAY_HEADER*)data;
	result = _parse_pg_info(pg, &ip, &port);
	switch(result){
		case URL_VAILD_NEW:
		case URL_VAILD_HIGH_PRI:
			ebm_plat_media_open();
			player_volume_update();
			ebm_play_cmd_open();
			rtp_net_start(ip, port);
			_log_pg_start(ip, port);
			break;
		case URL_VAILD_LAST:
			ebm_play_cmd_keepon();
			break;
		case URL_UNVAILD:
		default:
			break;	

	}

}



static void _parse_parm(struct cmd_param* p_data)
{
	unsigned char type= p_data->type;
	printf("type= #%d %s, len=%d\n", type, PARA_CMD_STR[type], p_data->len);
	switch(type)
	{
		case 1:
			if(p_data->len == 1)
				ebm_env_set_vol(p_data->data);
			break;
		case 2:
			if(p_data->len == 12)
				ebm_env_set_ip(&p_data->data);	
			break;	
		case 3:
			
			if(p_data->data == 0x1 && p_data->len == 7){

				unsigned short *port= (unsigned short*) (&p_data->data+5);
				ebm_env_set_backip(&p_data->data +1, *port);
			}
			else if(p_data->data == 0x2){
				printf("can't parse domain type ip addr\n");
			}
			break;
		case 4:
			if(p_data->data== PHY_ID_LEN )
				ebm_env_set_sourceid(&p_data->data+1+ PHY_ID_LEN);
			break;	
		case 5:
			if(p_data->data== 0x1 || p_data->data == 0x2)
				ebm_env_set_trumpet(p_data->data);
			break;
		case 6:
			if(p_data->len == 4){
				unsigned int *p_time;
				p_time= (unsigned int*)&p_data->data;
				ebm_env_set_systime(*p_time);
				
			}
			break;	
		case 7:
			ebm_env_set_back_tp(p_data->data);
			break;
		default:
			break;
	}
	

}


static void do_parse_parm(CMD_PARM_HEADER *cmd, unsigned int date_len)
{
	struct cmd_param *parm;
	unsigned char *p_data, total_nb;
	
	total_nb= cmd->terminal_nb;
	p_data= &cmd->terminal_nb +1;
	//printf("total_nb=%x pdata=%x\n", total_nb, *p_data);
	if(date_len > PARM_FILL_LEN)
		date_len-=PARM_FILL_LEN;
	else{
		printf("%s parm len not match\n", __func__);
		return;
	}

	while(total_nb && date_len >= 3)
	{
		parm= (struct cmd_param*)p_data;

		//printf("date_len=%d, parm-len=%d\n", date_len, parm->len);
		if(date_len-2 >= parm->len){
			_parse_parm(parm);
			total_nb--;
			date_len-= (2+ parm->len);
			p_data+= 2+ parm->len;
		}
		else{
			printf("%s parm len not match\n", __func__);
			break;
		}

	
	}

}

void parse_cmd_parm(unsigned char *cmd, unsigned int len)
{
	CMD_PARM_HEADER *head= (CMD_PARM_HEADER*)cmd;
	do_parse_parm(head, len);
}

void parse_req_sta(unsigned char *cmd, unsigned int len)
{
	CMD_PARM_HEADER *head= (CMD_PARM_HEADER*)cmd;
	do_parse_parm(head, len);
}




void convert_source_code(unsigned char *id, TYPE_SCODE *scode)
{
	memcpy(scode, id, 4);
	scode->town= id[4]<<4 | id[5]>>4;
	scode->village= (id[5]&0xf)<<8 | id[6];
	memcpy(&scode->type, &id[7], 5);

	if(0){
		dbg("province= %x\n", scode->province);
		dbg("city= %x\n", scode->city);
		
		dbg("county= %x\n", scode->county);
		
		dbg("town= %x\n", scode->town);
		dbg("village= %x\n", scode->village);
		
		dbg("type= %x\n", scode->type);
		
		dbg("type_idx= %x\n", scode->type_idx);
		dbg("sub_type= %x\n", scode->sub_type);
		dbg("sub_type_idx= %x\n", scode->sub_type_idx);
	}
}


static unsigned char _compare_source_code(TYPE_SCODE* my_scode, TYPE_SCODE* dset_scode)
{
	/*省*/
	if(my_scode->province != dset_scode->province)
		return 0;
	
	/*市*/
	if(dset_scode->city == 0)
		return 1;
	else if(my_scode->city != dset_scode->city)
		return 0;
	
	/*县*/
	if(dset_scode->town == 0)
		return 1;
	else if(my_scode->town != dset_scode->town)
		return 0;
	
	/*村*/
	if(dset_scode->village == 0)
		return 1;
	else if(my_scode->village != dset_scode->village)
		return 0;

	/*设备类型*/
	if(dset_scode->type == 0)
		return 1;
	else if(my_scode->type != dset_scode->type)
		return 0;

	/*设备类型序号*/
	if(dset_scode->type_idx == 0)
		return 1;
	else if(my_scode->type_idx  != dset_scode->type_idx)
		return 0;
	
	/*设备子类型*/
	if(dset_scode->sub_type == 0)
		return 1;
	else if(my_scode->sub_type  != dset_scode->sub_type)
		return 0;

	/*设备子类型序号*/
	if(dset_scode->sub_type_idx == 0)
		return 1;
	else if(my_scode->sub_type_idx != dset_scode->sub_type_idx)
		return 0;

	return 1;
}

/*
FE FD 01 00 53 34 27 AD 01 00 00 AB 
F4 52 04 25 00 00 00 01 03 01 01 01 
00 01 
F4 52 04 25 00 00 00 00 00 00 00 00 
01 
00 32 
F4 52 04 25 00 00 00 01 03 01  
30 30 FF 5E 72 B9 C1 5E 73 88 F0 01 3D 00 0C 75 64 70 3A 2F 2F 40 32 34 30 30 31 00 4A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 59 D7 66 39 


*/
unsigned char parse_msg(unsigned char *data, unsigned int len)
{	
	unsigned char my_scode_arry[12];
	TYPE_SCODE my_scode, dest_scode;
	TYPE_SCODE *mine= &my_scode, *dset= &dest_scode;
	
	unsigned char *pdata, *business_data;
	unsigned char business_type,scode_match=0;
	unsigned short scode_numb;
	int dlen;
	
	MSG_FIXED_HEADER2 *msg = (MSG_FIXED_HEADER2 *)data;
	if(msg->head_flag != VAILD_HEAD_FLAG || msg->version != VAILD_VERSION_FLAG){
		dbg("bad farme\n");
		return 0;
	}

	scode_numb= swap16(msg->items);
	dlen= len- 12*scode_numb -3; 
	pdata= &msg->items_arry;
	business_data= pdata + 12*scode_numb;
	if(dlen <= 0){
		printf("msg len too short\n");
		return 0;
	}
	
	ebm_env_get_sourceid(my_scode_arry, 12);
	convert_source_code(my_scode_arry, mine);
	while(scode_numb--){
		convert_source_code(pdata, dset);
		if(_compare_source_code(mine, dset)){
			scode_match=1;
			break;
		}
		pdata+= 12;
	}
	if(scode_match == 0){
		dbg("source code not match\n");
		return 0;
	}
	
	business_type= *business_data; 
	business_data+=1;
	unsigned short business_len= swap16(*(unsigned short*)business_data);
	
	business_data+=2;
	if(business_len != dlen){
		//dbg("business data len not match %d/%d\n", business_len, dlen);
	}
	
	switch(business_type)
	{
		case 0x1:
			parse_cmd_play(business_data);
			command_hearttick_wcnt_clear();
			break;
		case 0x2:
			printf("pg stop by ebm msg\n");
			if(is_current_pg_vaild()){
				sys_log("收到停播指令");
			}
			ebm_play_cmd_stop();
			break;	
		case 0x10:
			command_hearttick_wcnt_clear();
			break;	
		case 0x11:
			break;	
		case 0x12:
			
			parse_cmd_parm(business_data, dlen);
			break;
		default:
			break;

	}
	return 1;
}



void handle_ebm_msg(unsigned char *buf ,unsigned int len)
{
	MSG_FIXED_HEADER *msg;
	msg= (MSG_FIXED_HEADER *)buf;
	unsigned short msg_len;
#if 1
	{
		int i;
		ebmdbg_rec("rec msg %d Byte:\n", len);
		for(i=0; i< len;i++){
			ebmdbg_rec("%02X ", buf[i]);
		}
		ebmdbg_rec("\n");
	}
#endif	
	while(len > sizeof(MSG_FIXED_HEADER))
	{
		msg= (MSG_FIXED_HEADER *)buf;
		msg_len= swap16 (msg->data_len);
		if( len >= msg_len){
			if(0 == parse_msg(buf, msg_len))
				break;
			len-= msg_len;
			buf+= msg_len;
		}
		else
			break;
	}
}

unsigned char visit_pg_eflg(void)
{
	unsigned char ret=0;
	if(h_pg->radio_type == 4 )
		ret=1;
	return ret;
	
}

const char* visit_pg_net_info(void)
{
	const char* str[]={
		"无效",
		"发布演练",
		"模拟演练",
		"实际演练",
		"应急广播",
		"日常广播",
	};

	const char* str2[]={ 
		"缺省",
		"特大",
		"重大",
		"较大",
		"一般",
	};
	static char buf[40];
	int idx;
	if(1 == ebm_rtp_visit_netsta(NULL, NULL)&& is_current_pg_vaild()){
		unsigned char type= h_pg->radio_type;
		unsigned char rank= h_pg->rank;
		if(type > 5)
			type= 0;
		if(rank > 4)
			rank= 0;
		idx= snprintf(buf, 40, "%s", str[type]);
		if(idx > 0 && rank != 0){
			snprintf(&buf[idx], 40-idx, "(%s)", str2[rank]);
		}
	}
	else {
		return "待机中";
	}
	return buf;
}

const char* visit_pg_sourceid(void)
{
	static char buf[40];
	unsigned char i;
	if(is_current_pg_vaild()){
		for(i=0;i<18;i++){
			sprintf(&buf[i*2], "%02X", h_pg->source_id[i]);
		}
	}
	else {
		return NULL;
	}
	buf[39]=0;
	return buf;
}

const char* visit_pg_url(void)
{

	static char buf[PG_URL_LEN];
	if(1 == ebm_rtp_visit_netsta(NULL, NULL) && is_current_pg_vaild()){
		memcpy(buf, url_buf, PG_URL_LEN);
		buf[PG_URL_LEN-1]= 0;
		return buf;
	}
	else{
		return NULL;
	}
}

unsigned char visit_pg_vol(void)
{
	return h_pg->vaild? h_pg->vol : 0xff;
}



